package com.newegg.datafeed.adserving.adwords;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import com.google.api.ads.adwords.axis.v201809.cm.AdGroup;
import com.google.api.ads.adwords.axis.v201809.cm.AdGroupCriterion;
import com.google.api.ads.adwords.axis.v201809.cm.AdGroupCriterionOperation;
import com.google.api.ads.adwords.axis.v201809.cm.AdGroupCriterionReturnValue;
import com.google.api.ads.adwords.axis.v201809.cm.AdGroupCriterionServiceInterface;
import com.google.api.ads.adwords.axis.v201809.cm.ApiException;
import com.google.api.ads.adwords.axis.v201809.cm.BiddableAdGroupCriterion;
import com.google.api.ads.adwords.axis.v201809.cm.BiddingStrategyConfiguration;
import com.google.api.ads.adwords.axis.v201809.cm.Bids;
import com.google.api.ads.adwords.axis.v201809.cm.Campaign;
import com.google.api.ads.adwords.axis.v201809.cm.CpcBid;
import com.google.api.ads.adwords.axis.v201809.cm.Keyword;
import com.google.api.ads.adwords.axis.v201809.cm.KeywordMatchType;
import com.google.api.ads.adwords.axis.v201809.cm.Money;
import com.google.api.ads.adwords.axis.v201809.cm.NegativeAdGroupCriterion;
import com.google.api.ads.adwords.axis.v201809.cm.Operator;
import com.google.api.ads.adwords.axis.v201809.cm.UrlList;
import com.google.api.ads.adwords.axis.v201809.cm.UserStatus;
import com.google.api.ads.common.lib.exception.ValidationException;

public class KeywordService extends ADWordsParent {
	static AdGroupCriterionServiceInterface adGroupCriterionService;

	public KeywordService(String customerId) throws ValidationException {
		adGroupCriterionService = get(customerId, AdGroupCriterionServiceInterface.class);
	}

	public AdGroupCriterion[] add(long groupId) throws UnsupportedEncodingException, ApiException, RemoteException {
		// Create keywords.
		Keyword keyword1 = new Keyword();
		keyword1.setText("mars cruise");
		keyword1.setMatchType(KeywordMatchType.BROAD);
		Keyword keyword2 = new Keyword();
		keyword2.setText("space hotel");
		keyword2.setMatchType(KeywordMatchType.EXACT);

		// Create biddable ad group criterion.
		BiddableAdGroupCriterion keywordBiddableAdGroupCriterion1 = new BiddableAdGroupCriterion();
		keywordBiddableAdGroupCriterion1.setAdGroupId(groupId);
		keywordBiddableAdGroupCriterion1.setCriterion(keyword1);

		// You can optionally provide these field(s).
		keywordBiddableAdGroupCriterion1.setUserStatus(UserStatus.PAUSED);

		String encodedFinalUrl = String.format("http://example.com?kw=%s",
				URLEncoder.encode(keyword1.getText(), UTF_8.name()));
		keywordBiddableAdGroupCriterion1.setFinalUrls(new UrlList(new String[] { encodedFinalUrl }));

		BiddingStrategyConfiguration biddingStrategyConfiguration = new BiddingStrategyConfiguration();
		CpcBid bid = new CpcBid();
		bid.setBid(new Money(null, 10000000L));
		biddingStrategyConfiguration.setBids(new Bids[] { bid });
		keywordBiddableAdGroupCriterion1.setBiddingStrategyConfiguration(biddingStrategyConfiguration);

		NegativeAdGroupCriterion keywordNegativeAdGroupCriterion2 = new NegativeAdGroupCriterion();
		keywordNegativeAdGroupCriterion2.setAdGroupId(groupId);
		keywordNegativeAdGroupCriterion2.setCriterion(keyword2);

		// Create operations.
		AdGroupCriterionOperation keywordAdGroupCriterionOperation1 = new AdGroupCriterionOperation();
		keywordAdGroupCriterionOperation1.setOperand(keywordBiddableAdGroupCriterion1);
		keywordAdGroupCriterionOperation1.setOperator(Operator.ADD);
		AdGroupCriterionOperation keywordAdGroupCriterionOperation2 = new AdGroupCriterionOperation();
		keywordAdGroupCriterionOperation2.setOperand(keywordNegativeAdGroupCriterion2);
		keywordAdGroupCriterionOperation2.setOperator(Operator.ADD);

		AdGroupCriterionOperation[] operations = new AdGroupCriterionOperation[] { keywordAdGroupCriterionOperation1,
				keywordAdGroupCriterionOperation2 };

		// Add keywords.
		AdGroupCriterionReturnValue result = adGroupCriterionService.mutate(operations);
		return result.getValue();
	}

	public static void main(String[] args)
			throws ApiException, RemoteException, ValidationException, UnsupportedEncodingException {
		String customerId = "698-254-6209";
		List<Campaign> campaigns = new CampaignService(customerId).listCampaign();
		campaigns.forEach(camp -> System.out.println("[Campaign] " + camp.getId() + " -> " + camp.getName()));
		Random ran = new Random();
		Campaign choosedCamp = campaigns.get(ran.nextInt(campaigns.size()));
		System.out.println("Random Choosed Campaign: " + choosedCamp.getId() + " -> " + choosedCamp.getName());

		// add ad group
		ADGroupService adGroupService = new ADGroupService(customerId);
		adGroupService.addADGroup(choosedCamp.getId());
		
		List<AdGroup> adGroups = adGroupService.listAdGroups(choosedCamp.getId());
		adGroups.forEach(adGroup -> System.out.println("[AdGroup] " + adGroup.getId() + " -> " + adGroup.getName()));
		AdGroup choosedAdGroup = adGroups.get(ran.nextInt(adGroups.size()));
		System.out.println("Random Choosed AdGroup: " + choosedAdGroup.getId() + " -> " + choosedAdGroup.getName());

		// add keywords
		AdGroupCriterion[] adGroupCriterions = new KeywordService(customerId).add(choosedAdGroup.getId());
		Arrays.asList(adGroupCriterions).forEach(adGroupCriterion -> System.out.println(adGroupCriterion.toString()));
	}
}
